package com.swiftride.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.swiftride.constants.Constants;
import com.swiftride.constants.GlobalExceptionCode;
import com.swiftride.exception.GlobalException;
import com.swiftride.feign.AppRuleFeign;
import com.swiftride.feign.CustomerFeign;
import com.swiftride.mapper.OrderMapper;
import com.swiftride.pojo.domain.Order;
import com.swiftride.pojo.domain.OrderBill;
import com.swiftride.pojo.domain.OrderProfitsharing;
import com.swiftride.pojo.dto.DriverSettingDto;
import com.swiftride.pojo.dto.LoginInfoDto;
import com.swiftride.pojo.param.*;
import com.swiftride.pojo.result.PricingResult;
import com.swiftride.pojo.result.SplitAccountResult;
import com.swiftride.pojo.vo.DriverLocationVo;
import com.swiftride.pojo.vo.DriverOrderMonthVo;
import com.swiftride.pojo.vo.OrderDetailVo;
import com.swiftride.pojo.vo.OrderInfoVo;
import com.swiftride.result.R;
import com.swiftride.service.IOrderBillService;
import com.swiftride.service.IOrderProfitsharingService;
import com.swiftride.service.IOrderService;
import com.swiftride.template.RedisGeoTemplate;
import com.swiftride.utils.AssertUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.consumer.DefaultMQPullConsumer;
import org.apache.rocketmq.client.consumer.PullResult;
import org.apache.rocketmq.client.consumer.PullStatus;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.client.producer.SendStatus;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.GeoResult;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;


/**
 * <p>
 * 订单表 服务实现类
 * </p>
 *
 * @author wy
 * @since 2024-08-10
 */
@Slf4j
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {

    //----------服务----------
    @Autowired
    private IOrderBillService orderBillService;

    @Autowired
    private IOrderProfitsharingService orderProfitSharingService;

    //----------feign接口----------
    @Autowired
    private AppRuleFeign appRuleFeign;

    @Autowired
    private CustomerFeign customerFeign;

    //----------redis组件----------
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private RedisGeoTemplate redisGeoTemplate;

    //----------rocketmq组件----------
    @Autowired
    private RocketMQTemplate rocketMqTemplate;

    @Autowired
    private DefaultMQPullConsumer pullConsumer;

    //----------业务实现方法----------
    @Transactional
    @Override
    public Order createOrder(CreateOrderParam createOrderParam) {
        //1. 参数校验 - JSR303
        //2. 业务校验-乘客是否有进行中的订单
        long customerId = StpUtil.getLoginIdAsLong();
        Order order = super.getOne(new LambdaQueryWrapper<Order>()
                .eq(Order::getCustomerId, customerId)
                .in(Order::getStatus, Constants.Order.CUSTOMER_ORDER_IN_PROGRESS));
        AssertUtil.isNull(order, GlobalExceptionCode.DATA_EXCEPTION);
        //3. 业务实现
        //3.1 调用计价服务获取价格信息
        PricingParam pricingParam = new PricingParam();
        pricingParam.setStartTime(new Date());
        pricingParam.setExpectsMileage(createOrderParam.getExpectsMileage());
        R<PricingResult> pricing = appRuleFeign.pricing(pricingParam);
        if (!pricing.isSuccess()) {
            throw new GlobalException(GlobalExceptionCode.SERVICE_REQUEST_ERROR);
        }
        PricingResult pricingResult = pricing.getData();
        //3.2 从redis中获取当前乘客的登录信息
        String loginIdKey = String.format(Constants.Redis.LOGIN_REDIS_KEY, customerId);
        LoginInfoDto loginInfoDto = (LoginInfoDto) redisTemplate.opsForValue().get(loginIdKey);
        AssertUtil.isNotNull(loginInfoDto, GlobalExceptionCode.DATA_STALENESS);
        //3.3 保存订单表
        String orderNo = UUID.randomUUID().toString();
        BigDecimal realOrderAmount = pricingResult.getOrderAmount();
        order = new Order().setOrderNo(orderNo).setCustomerId(customerId).setExpectsOrderAmount(realOrderAmount);
        saveOrder(order, loginInfoDto, createOrderParam);
        //3.4 将订单信息添加到redis
        String orderInfoKey = String.format(Constants.Redis.ORDER_INFO_KEY, orderNo);
        redisTemplate.opsForValue().set(orderInfoKey, order);
        //3.5 发送到rocketmq延迟取消消息
        pushMessage(order);
        //3.6 调用geoRadius接口获取中心点指定半径内的数据
        Point point = new Point(createOrderParam.getStartPlaceLongitude(), createOrderParam.getStartPlaceLatitude());
        List<GeoResult<RedisGeoCommands.GeoLocation<Object>>> geoResults =
                redisGeoTemplate.geoRadius(redisTemplate, Constants.Redis.DRIVER_LOCATION_KEY, point);
        //3.7 推送订单信息给司机
        OrderInfoVo orderInfoVo = new OrderInfoVo();
        orderInfoVo.setOrderNo(orderNo);
        orderInfoVo.setOrderAmount(realOrderAmount);
        pushOrder(orderInfoVo, createOrderParam, geoResults);
        //3.8 保存订单账单表
        saveOrderBill(order, pricingResult);
        //3.9 返回订单信息
        return order;
    }

    private void pushMessage(Order order) {
        Message<String> message = MessageBuilder.withPayload(order.getOrderNo()).build();
        for (int i = 0; true; i++) {
            SendResult sendResult = rocketMqTemplate.syncSend(
                    Constants.RocketMQ.ORDER_TIMEOUT_CANCEL_TOPIC + ":" + Constants.RocketMQ.ORDER_TIMEOUT_CANCEL_TAG,
                    message, 3000, 5);
            if (sendResult.getSendStatus().equals(SendStatus.SEND_OK)) {
                break;
            }
            if (i == 2) {
                throw new GlobalException(GlobalExceptionCode.SERVICE_ERROR);
            }
        }
    }

    private void pushOrder(OrderInfoVo orderInfoVo, CreateOrderParam createOrderParam, List<GeoResult<RedisGeoCommands.GeoLocation<Object>>> geoResults) {
        orderInfoVo.setMileage(createOrderParam.getExpectsMileage());
        orderInfoVo.setMinutes(createOrderParam.getExpectMinutes());
        orderInfoVo.setStartPlace(createOrderParam.getStartPlace());
        orderInfoVo.setEndPlace(createOrderParam.getEndPlace());
        //3.6 对数据进行过滤的同时填写订单信息并发送订单消息到司机对应的rocketmq中
        List<GeoResult<RedisGeoCommands.GeoLocation<Object>>> list = geoResults.stream().filter(geoResult -> {
            //通过redis获取司机配置
            String driveId = String.valueOf(geoResult.getContent().getName());
            String driverKey = String.format(Constants.Redis.DRIVER_ONLINE_KEY, driveId);
            DriverSettingDto driverSettingDto = (DriverSettingDto) redisTemplate.opsForValue().get(driverKey);
            if (ObjectUtil.isNull(driverSettingDto)) {
                return false;
            }
            //给符合条件的司机发送订单消息
            Double orderDistance = geoResult.getDistance().getValue();
            if (driverSettingDto.getOrderDistance() > orderDistance
                    && BigDecimal.valueOf(driverSettingDto.getRangeDistance()).compareTo(createOrderParam.getExpectsMileage()) > 0) {
                orderInfoVo.setDriverId(driveId);
                orderInfoVo.setDistance(orderDistance);
                Message<OrderInfoVo> message = MessageBuilder.withPayload(orderInfoVo).build();
                SendResult sendResult = rocketMqTemplate.syncSend(String.format(Constants.RocketMQ.DRIVER_PULL_ORDER_TOPIC_TAG, driveId), message);
                if (!sendResult.getSendStatus().equals(SendStatus.SEND_OK)) {
                    log.error("给司机订单发送MQ失败,司机ID为{}", driveId);
                }
                return true;
            }
            return false;
        }).toList();
        //@TODO 没有找到司机进行其他功能
        if (list.size() == 0) {
            throw new GlobalException("没有找到对应的司机");
        }
    }

    private void saveOrder(Order order, LoginInfoDto loginInfoDto, CreateOrderParam createOrderParam) {
        order.init();
        order.setCustomerPhoto(loginInfoDto.getAvatar());
        order.setCustomerName(loginInfoDto.getName());
        order.setCustomerPhone(loginInfoDto.getPhone());
        BeanUtil.copyProperties(createOrderParam, order);
        super.save(order);
    }

    private void saveOrderBill(Order order, PricingResult pricingResult) {
        OrderBill orderBill = new OrderBill();
        orderBill.init();
        orderBill.setOrderId(order.getId());
        orderBill.setOrderNo(order.getOrderNo());
        BeanUtil.copyProperties(pricingResult, orderBill);
        orderBillService.save(orderBill);
    }

    @Override
    public List<OrderInfoVo> driverPullOrder() {
        //司机的ID
        Long driverId = Long.valueOf(StpUtil.getLoginId().toString());
        try {
            //订阅消息队列，指定topic
            //Constants.MQ.TOPIC_ORDER：指定获取某个topic下的队列
            Set<MessageQueue> messageQueues = pullConsumer.fetchSubscribeMessageQueues(Constants.RocketMQ.DRIVER_PULL_ORDER_TOPIC);
            //封装结果
            List<OrderInfoVo> result = new ArrayList<>();
            for (MessageQueue messageQueue : messageQueues) {
                //通过偏移量来获取消息 ：当前队列的消费位置
                long offset = pullConsumer.fetchConsumeOffset(messageQueue, true);
                //拉取消息，需要指定tag
                String tags = String.format(Constants.RocketMQ.DRIVER_PULL_ORDER_TAG, driverId);
                PullResult pullResult = pullConsumer.pull(messageQueue, tags, offset, 5);
                //找到消息
                if (pullResult != null && pullResult.getPullStatus().equals(PullStatus.FOUND)) {
                    //拿到消息列表
                    List<MessageExt> messageExtList = pullResult.getMsgFoundList();
                    if (messageExtList == null || messageExtList.isEmpty()) {
                        continue;
                    }
                    for (MessageExt messageExt : messageExtList) {
                        //拿到消息内容，转换为订单对象
                        String message = new String(messageExt.getBody(), StandardCharsets.UTF_8);
                        OrderInfoVo orderMessage = JSON.parseObject(message, OrderInfoVo.class);
                        //添加到结果列表
                        result.add(orderMessage);
                        log.info("获取订单消息 {}", orderMessage);
                    }
                }
                //重要：修改消息的消费位置，如果位置不后移，消息会一直被消费
                pullConsumer.updateConsumeOffset(messageQueue, pullResult.getNextBeginOffset());
            }
            return result;
        } catch (Exception e) {
            log.error("拉取订单消息时发生错误", e);
            // 返回一个空列表而不是null，避免调用者处理null
            return Collections.emptyList();
        }
    }

    @Transactional
    @Override
    public Order killOrder(String orderNo) {
        //1.参数校验 - JSR303
        //2.业务校验
        String orderInfoKey = String.format(Constants.Redis.ORDER_INFO_KEY, orderNo);
        Object orderObject = redisTemplate.opsForValue().get(orderInfoKey);
        AssertUtil.isNotNull(orderObject, GlobalExceptionCode.DATA_STALENESS);
        //3.业务实现
        //3.1 加redisson锁
        String redissonOrderKey = String.format(Constants.Redis.REDISSON_ORDER_KEY, orderNo);
        RLock lock = redissonClient.getLock(redissonOrderKey);
        try {
            //1.锁
            boolean isTryLock = lock.tryLock();
            AssertUtil.isTrue(isTryLock, GlobalExceptionCode.DATA_STALENESS);
            //2.删除redis中的订单信息
            redisTemplate.delete(orderInfoKey);
            //3.修改订单落库
            Order order = (Order) orderObject;
            //司机相关信息
            long driverId = StpUtil.getLoginIdAsLong();
            order.setDriverId(driverId);
            String loginKey = String.format(Constants.Redis.LOGIN_REDIS_KEY, driverId);
            LoginInfoDto loginInfoDto = (LoginInfoDto) redisTemplate.opsForValue().get(loginKey);
            AssertUtil.isNotNull(loginInfoDto, GlobalExceptionCode.DATA_EXCEPTION);
            order.setDriverPhoto(loginInfoDto.getAvatar());
            order.setDriverName(loginInfoDto.getName());
            order.setDriverPhone(loginInfoDto.getPhone());
            //订单状态信息
            order.setStatus(Constants.Order.RECEIVED_ORDER);
            Date now = new Date();
            order.setAcceptTime(now);
            order.setUpdateTime(now);
            super.updateById(order);
            return order;
        } finally {
            if (lock.isLocked()) {
                lock.unlock();
            }
        }
    }

    @Transactional
    @Override
    public void customerCancelOrder(String orderNo) {
        //1.参数校验 JSR303
        //2.业务校验--获取到的订单的状态必须是可取消订单状态且订单乘客必须是当前乘客
        long customerId = StpUtil.getLoginIdAsLong();
        Order order = super.getOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderNo, orderNo)
                .eq(Order::getCustomerId, customerId)
                .in(Order::getStatus, Constants.Order.ORDER_CANCELABLE));
        AssertUtil.isNotNull(order, GlobalExceptionCode.DATA_EXCEPTION);
        //3.业务实现
        //3.1 删除redis中的订单
        String orderInfoKey = String.format(Constants.Redis.ORDER_INFO_KEY, orderNo);
        redisTemplate.delete(orderInfoKey);
        //3.2 修改订单状态和更新时间
        order.setStatus(Constants.Order.CUSTOMER_CANCEL);
        order.setUpdateTime(new Date());
        super.updateById(order);
        //3.3 保存乘客罚款
        Integer status = order.getStatus();
        if (Constants.Order.RECEIVED_ORDER.equals(status) || Constants.Order.DRIVER_ARRIVED.equals(status)) {
            BigDecimal fineAmount = order.getExpectsOrderAmount().multiply(BigDecimal.valueOf(status)).multiply(new BigDecimal("0.1"));
            CustomerFineParam customerFineParam = new CustomerFineParam();
            customerFineParam.setCustomerId(customerId);
            customerFineParam.setOrderId(order.getId());
            customerFineParam.setAmount(fineAmount);
            customerFineParam.setRemark("取消订单罚款");
            R result = customerFeign.saveCustomerFine(customerFineParam);
            AssertUtil.isTrue(result.isSuccess(), GlobalExceptionCode.SERVICE_REQUEST_ERROR);
        }
    }

    @Transactional
    @Override
    public void driverCancelOrder(String orderNo) {
        //1.参数校验 JSR303
        //2.业务校验--获取到的订单的状态必须是可取消订单状态且订单司机必须是当前司机
        long driverId = StpUtil.getLoginIdAsLong();
        Order order = super.getOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderNo, orderNo)
                .eq(Order::getDriverId, driverId)
                .in(Order::getStatus, Constants.Order.ORDER_CANCELABLE));
        AssertUtil.isNotNull(order, GlobalExceptionCode.DATA_EXCEPTION);
        //3.业务实现
        //1.保存订单信息
        order.setStatus(Constants.Order.DRIVER_CALCEL);
        order.setUpdateTime(new Date());
        super.updateById(order);
    }

    @Transactional
    @Override
    public void arriveStartPlace(String orderNo) {
        //2.业务校验
        Order order = super.getOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderNo, orderNo)
                .eq(Order::getStatus, Constants.Order.RECEIVED_ORDER));
        AssertUtil.isNotNull(order, GlobalExceptionCode.DATA_EXCEPTION);
        //3,业务实现
        order.setStatus(Constants.Order.DRIVER_ARRIVED);
        Date now = new Date();
        order.setArriveTime(now);
        order.setUpdateTime(now);
        super.updateById(order);
    }

    @Transactional
    @Override
    public void startDriving(String orderNo) {
        //@TODO 订单防刷
        //2.业务校验
        Order order = super.getOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderNo, orderNo)
                .eq(Order::getStatus, Constants.Order.DRIVER_ARRIVED));
        AssertUtil.isNotNull(order, GlobalExceptionCode.DATA_EXCEPTION);
        OrderBill orderBill = orderBillService.getOne(new LambdaQueryWrapper<OrderBill>().eq(OrderBill::getOrderNo, orderNo));
        AssertUtil.isNotNull(orderBill, GlobalExceptionCode.DATA_EXCEPTION);
        //3.业务实现
        Date now = new Date();
        //3.1 计算等待金额,保存订单账单表
        Integer waitingMinute = (int) (now.getTime() - order.getArriveTime().getTime()) / (1000 * 60);
        BigDecimal waitingAmount = new BigDecimal("0");
        Integer freeBaseWaitingMinute = orderBill.getFreeBaseWaitingMinute();
        if (waitingMinute.compareTo(freeBaseWaitingMinute) > 0) {
            //等待金额 = (等待时间 - 免费等待时间里程) * 每分钟等待费用
            waitingAmount = BigDecimal.valueOf((waitingMinute - freeBaseWaitingMinute))
                    .multiply(orderBill.getExceedBaseMileageAmount());
        }
        orderBill.setWaitingMinute(waitingMinute);
        orderBill.setWaitingAmount(waitingAmount);
        orderBill.setUpdateTime(now);
        orderBillService.updateById(orderBill);
        //3.2 保存订单信息
        order.setStatus(Constants.Order.START_DRIVING);
        order.setStartTime(now);
        order.setUpdateTime(now);
        super.updateById(order);
    }

    @Transactional
    @Override
    public void endDriving(String orderNo, BigDecimal totalDistance) {
        //2.业务校验
        Order order = super.getOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderNo, orderNo)
                .eq(Order::getStatus, Constants.Order.START_DRIVING));
        AssertUtil.isNotNull(order, GlobalExceptionCode.DATA_EXCEPTION);

        OrderBill orderBill = orderBillService.getOne(new LambdaQueryWrapper<OrderBill>().eq(OrderBill::getOrderNo, orderNo));
        AssertUtil.isNotNull(orderBill, GlobalExceptionCode.DATA_EXCEPTION);
        //3.2 计算里程金额和返程金额
        //行驶金额 = 起步价 + (行驶里程 - 起步里程) * 每公里行驶费用
        BigDecimal baseMileage = orderBill.getBaseMileage();
        BigDecimal mileageAmount = totalDistance.compareTo(baseMileage) > 0 ?
                orderBill.getMileageAmount().add(totalDistance.subtract(baseMileage)
                        .multiply(orderBill.getExceedBaseMileageAmount())) : orderBill.getMileageAmount();
        //返程费用 = (返程里程 - 免费返程里程) * 每公里返程费用
        BigDecimal freeBaseReturnMileage = orderBill.getFreeBaseReturnMileage();
        BigDecimal returnAmount = totalDistance.compareTo(freeBaseReturnMileage) > 0 ?
                (totalDistance.subtract(freeBaseReturnMileage))
                        .multiply(orderBill.getExceedBaseReturnEveryKmAmount()) : new BigDecimal("0");
        BigDecimal realOrderAmount = mileageAmount.add(orderBill.getWaitingAmount()).add(returnAmount);
        //3.2 保存订单账单信息
        Date now = new Date();
        orderBill.setMileageAmount(mileageAmount);
        orderBill.setReturnAmount(returnAmount);
        orderBill.setRealOrderAmount(realOrderAmount);
        orderBill.setUpdateTime(now);
        orderBillService.updateById(orderBill);
        //3.3 保存订单信息
        order.setRealMileage(totalDistance);
        order.setReturnMileage(totalDistance);
        order.setRealOrderAmount(realOrderAmount);
        order.setStatus(Constants.Order.END_DRIVING);
        order.setEndTime(now);
        order.setUpdateTime(now);
        super.updateById(order);
    }

    @Transactional
    @Override
    public void confirmFees(ConfirmFeesParam confirmFeesParam) {
        //1.参数校验
        //2.业务校验
        String orderNo = confirmFeesParam.getOrderNo();
        Order order = super.getOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderNo, orderNo)
                .eq(Order::getStatus, Constants.Order.END_DRIVING));
        AssertUtil.isNotNull(order, GlobalExceptionCode.DATA_EXCEPTION);
        OrderBill orderBill = orderBillService.getOne(new LambdaQueryWrapper<OrderBill>().eq(OrderBill::getOrderNo, orderNo));
        AssertUtil.isNotNull(orderBill, GlobalExceptionCode.DATA_EXCEPTION);
        //3.业务实现
        //3.1 计算总金额
        BigDecimal tollFee = confirmFeesParam.getTollFee();
        BigDecimal parkingFee = confirmFeesParam.getParkingFee();
        BigDecimal otherFree = confirmFeesParam.getOtherFree();
        BigDecimal realOrderAmount = orderBill.getMileageAmount().add(orderBill.getWaitingAmount())
                .add(orderBill.getReturnAmount()).add(tollFee).add(parkingFee).add(otherFree);
        //3.2 计算订单分账表并保存
        R<SplitAccountResult> pricingResultR = appRuleFeign.splitAccount(realOrderAmount);
        AssertUtil.isTrue(pricingResultR.isSuccess(), GlobalExceptionCode.SERVICE_REQUEST_ERROR);
        SplitAccountResult splitAccountResult = pricingResultR.getData();
        OrderProfitsharing orderProfitsharing = orderProfitSharingService.getOne(new LambdaQueryWrapper<OrderProfitsharing>()
                .eq(OrderProfitsharing::getOrderNo, orderNo));
        if (ObjectUtil.isNull(orderProfitsharing)) {
            orderProfitsharing = new OrderProfitsharing();
        }
        orderProfitsharing.setOrderId(order.getId());
        orderProfitsharing.setOrderNo(orderNo);
        orderProfitsharing.setOrderAmount(realOrderAmount);
        orderProfitsharing.setStatus(0);
        BeanUtil.copyProperties(splitAccountResult, orderProfitsharing);
        orderProfitSharingService.saveOrUpdate(orderProfitsharing);
        //3.3 更新订单账单表
        Date date = new Date();
        orderBill.setTollAmount(tollFee);
        orderBill.setParkingAmount(parkingFee);
        orderBill.setOtherAmount(otherFree);
        orderBill.setRealOrderAmount(realOrderAmount);
        orderBill.setUpdateTime(date);
        orderBillService.updateById(orderBill);
        //3.4 更新订单
        order.setRealOrderAmount(realOrderAmount);
        order.setUpdateTime(date);
        super.updateById(order);
    }

    //----------业务查询方法----------
    @Override

    public Order getProgressOrder(String orderNo) {
        Order order = super.getOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderNo, orderNo)
                .in(Order::getStatus, Constants.Order.DRIVER_ORDER_IN_PROGRESS));
        AssertUtil.isNotNull(order, GlobalExceptionCode.DATA_EXCEPTION);
        return order;
    }

    @Override
    public OrderDetailVo getCustomerOrderDetail(String orderNo) {
        //2.业务校验
        Order order = super.getOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderNo, orderNo));
        AssertUtil.isNotNull(order, GlobalExceptionCode.DATA_EXCEPTION);
        OrderBill orderBill = orderBillService.getOne(new LambdaQueryWrapper<OrderBill>().eq(OrderBill::getOrderNo, orderNo));
        AssertUtil.isNotNull(orderBill, GlobalExceptionCode.DATA_EXCEPTION);
        //3.业务实现
        OrderDetailVo orderDetailVo = BeanUtil.copyProperties(order, OrderDetailVo.class);
        BeanUtil.copyProperties(orderBill, orderDetailVo);
        return orderDetailVo;
    }

    @Override
    public OrderDetailVo getDriverOrderDetail(String orderNo) {
        OrderDetailVo orderDetailVo = getCustomerOrderDetail(orderNo);
        OrderProfitsharing orderProfitsharing = orderProfitSharingService.getOne(new LambdaQueryWrapper<OrderProfitsharing>()
                .eq(OrderProfitsharing::getOrderNo, orderNo));
        AssertUtil.isNotNull(orderProfitsharing, GlobalExceptionCode.DATA_EXCEPTION);
        BeanUtil.copyProperties(orderProfitsharing, orderDetailVo);
        return orderDetailVo;
    }

    @Override
    public Boolean getOrderAccept(String orderNo) {
        String orderInfoKey = String.format(Constants.Redis.ORDER_INFO_KEY, orderNo);
        Object order = redisTemplate.opsForValue().get(orderInfoKey);
        return ObjectUtil.isNull(order);
    }

    @Override
    public DriverLocationVo getDriverLocation(String driverId) {
        List<Point> position = redisTemplate.opsForGeo().position(Constants.Redis.DRIVER_LOCATION_KEY, driverId);
        AssertUtil.isNotNull(position, GlobalExceptionCode.DATA_STALENESS);
        DriverLocationVo driverLocationVo = new DriverLocationVo();
        driverLocationVo.setLongitude(position.get(0).getX());
        driverLocationVo.setLatitude(position.get(0).getY());
        return driverLocationVo;
    }

    //----------小程序页面退出后重新进入,维护页面的方法----------
    @Override
    public Order getCustomerLastOrder() {
        //查询该乘客最近一次订单数据
        return super.getOne(new LambdaQueryWrapper<Order>()
                .eq(Order::getCustomerId, StpUtil.getLoginIdAsLong())
                .orderByDesc(Order::getCreateTime)
                .last("limit 1"));
    }

    @Override
    public Order getDriverWorkStatus() {
        String loginIdStr = StpUtil.getLoginIdAsString();
        String driverOnlineKey = String.format(Constants.Redis.DRIVER_ONLINE_KEY, loginIdStr);
        //查询司机最近一次订单的状态1到4来代表工作状态
        long driverId = StpUtil.getLoginIdAsLong();
        Order order = super.getOne(new LambdaQueryWrapper<Order>().eq(Order::getDriverId, driverId)
                .in(Order::getStatus, Constants.Order.DRIVER_ORDER_IN_PROGRESS)
                .orderByDesc(Order::getCreateTime)
                .last("limit 1"));
        //如果查询到则返回工作状态,否则取redis中查询司机是否处于上线状态,是则用状态0来代表上线,否则返回null代表下线状态
        if (ObjectUtil.isNotNull(order)) {
            return order;
        } else if (Boolean.TRUE.equals(redisTemplate.hasKey(driverOnlineKey))) {
            return new Order().setStatus(0);
        }
        return null;
    }

    @Override
    @Transactional
    public List<DriverOrderMonthVo> getDriverOrder(DriverOrderParam driverOrderParam) {
        //1.参数校验--页数和行数必须大于等于1
        Integer page = driverOrderParam.getPage();
        Integer rows = driverOrderParam.getRows();
        if (page < 1 || rows < 1) {
            throw new GlobalException(GlobalExceptionCode.PARAM_ERROR);
        }
        //2.业务校验
        //3.业务实现
        //3.1 获取司机订单列表
        List<Order> driverOrderList = super.list(new LambdaQueryWrapper<Order>().eq(Order::getDriverId, StpUtil.getLoginIdAsLong())
                .last("limit " + (page - 1) * rows + "," + rows));
        //3.2 按月份分组
        Map<String, List<Order>> ordersByMonth = driverOrderList.stream()
                .collect(Collectors.groupingBy(order -> {
                    // 将 Date 转换为 LocalDate
                    LocalDate acceptDate = order.getAcceptTime().toInstant()
                            .atZone(ZoneId.systemDefault())
                            .toLocalDate();
                    // 获取月份和年份，格式为 "YYYY-MM"
                    return acceptDate.format(DateTimeFormatter.ofPattern("yyyy-MM"));
                }));
        // 转换为 DriverOrderMonthVo 列表
        return ordersByMonth.entrySet().stream()
                .map(entry -> {
                    DriverOrderMonthVo monthVo = new DriverOrderMonthVo();
                    monthVo.setMonth(entry.getKey());  // 设置月份
                    monthVo.setOrders(entry.getValue());  // 设置该月份的订单列表
                    return monthVo;
                }).toList();
    }
}
